import { inject, onBeforeUnmount, onMounted, getCurrentInstance } from "vue";
import { useEditorPlugins, VueFlowEditorProvider } from "@/editor/editor";
import { G6 } from "@/g6/g6";
import { useBehavior } from "@/behavior";
import { GraphStyle } from "@/utils/styles";
import { registerShape } from "@/shape";
import { formatNodeModel } from "@/utils/utils";

registerShape(G6);

export default {
  name: "vue-flow-editor-canvas",
  props: {
    data: { type: Object }, // 渲染的数据
    miniMap: { type: [Boolean, Object], default: true }, // 是否需要缩略图
    grid: { type: [Boolean, Object], default: true }, // 是否需要网格
  },
  setup(props, context) {
    const { ctx } = getCurrentInstance() as any;

    const { editorState, commander, props: editorProps } = inject(VueFlowEditorProvider) as any;

    function onMouseenter(e: MouseEvent) {
      commander.initEvent();
    }

    function onMouseout(e: MouseEvent) {
      commander.destroyEvent();
    }

    function refresh() {
      if (!!editorState.graph) {
        editorState.graph.destroy();
      }
      const target = ctx.$refs.target as HTMLElement;
      const { offsetHeight: height, offsetWidth: width } = ctx.$refs.root as HTMLElement;
      const behaviors = useBehavior({
        multipleSelect: editorState.props.multipleSelect,
        dragEdge: {
          disabled: editorState.props.disabledDragEdge,
          beforeAdd: editorState.props.beforeAdd,
          afterAdd: editorState.props.afterAdd,
        },
      });

      const graph = new G6.Graph({
        container: target as HTMLElement,
        width,
        height,

        modes: {
          edit: [...behaviors],
        },

        ...GraphStyle.default,
      });

      const $read = graph.read;
      graph.read = (data) => {
        let { nodes, edges } = data || {};
        nodes = nodes || [];
        edges = edges || [];

        nodes.forEach((node) => formatNodeModel(node, editorProps.activityConfig));

        data = { nodes, edges };

        $read.apply(graph, [data]);
      };

      graph.setMode("edit");
      graph.read(props.data);
      useEditorPlugins(props, graph);
      editorState.setGraph(graph);
    }

    function onResize() {
      refresh();
    }

    onMounted(() => {
      const target = ctx.$refs.target as HTMLElement;
      target.addEventListener("mouseenter", onMouseenter);
      target.addEventListener("mouseout", onMouseout);
      window.addEventListener("resize", onResize);

      refresh();
    });

    onBeforeUnmount(() => {
      const target = ctx.$refs.target as HTMLElement;
      target.removeEventListener("mouseenter", onMouseenter);
      target.removeEventListener("mouseout", onMouseout);
      window.removeEventListener("resize", onResize);

      commander.destroyEvent();
    });

    return () => (
      <div class="vue-flow-editor-canvas" ref="root">
        <div class="vue-flow-editor-canvas-target" ref="target" />
      </div>
    );
  },
};
